package code16_thread;

public class Test05 {

	public static void main(String[] args) {
		// 同步代码块
//		Ticket1 ticket = new Ticket1();
//		Object obj = new Object();// 充当锁对象
//		ticket.obj = obj;// 设置锁
//		Thread t1 = new Thread(ticket, "窗口1");
//		Thread t2 = new Thread(ticket, "窗口2");
//		t1.start();
//		t2.start();
		
		// 同步方法
		Ticket ticket = new Ticket();
		Thread t1 = new Thread(ticket, "窗口1");
		Thread t2 = new Thread(ticket, "窗口2");
		t1.start();
		t2.start();
	}
	
}
class Ticket implements Runnable {
	int num = 50;// 票
	@Override
	public void run() {
		while (true) {
			// 必须要保证, 多个线程看到的锁对象是相同的
			// 锁对象的不能改变(对象的地址)
			
			if (num <= 0) {
				break;
			}
			// 非静态的同步方法
			//sell();
			
			// 静态的同步方法
			sell2(this);
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	// 同步方法, 需要把核心代码, 放入其中
	// 同步方法, 不需要指明 锁对象
	// 非静态的 同步方法 的 锁对象 是 this, 必须要保证所有的线程看到的 this 对象是相同的
	public synchronized void sell() {
		if (num > 0) {// 有票, 才卖
			Thread t = Thread.currentThread();
			System.out.println(t.getName() + " 卖票: " + num);
			num--;
		}
	}
	
	// 静态的 同步方法 的 锁对象 是 当前类的 Class 对象
	public static synchronized void sell2(Ticket ticket) {
		if (ticket.num > 0) {// 有票, 才卖
			Thread t = Thread.currentThread();
			System.out.println(t.getName() + " 卖票: " + ticket.num);
			ticket.num--;
		}
	}
}
// 同步代码
class Ticket1 implements Runnable {
	int num = 50;// 票
	public Object obj;// 锁对象
	@Override
	public void run() {
		while (true) {
			Thread t = Thread.currentThread();
			// 必须要保证, 多个线程看到的锁对象是相同的
			// 锁对象的不能改变(对象的地址)
			//synchronized (obj) {
			synchronized (Ticket1.class) {// 一般没有要求锁对象是什么时, 通常会使用当前类的 Class对象 作为锁对象
				// 包裹核心代码
				if (num <= 0) {
					break;
				}
				System.out.println(t.getName() + " 卖票: " + num);
				num--;
			}
			
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}